Fix left+right tab-stop column layout (signature blocks) - #14
Conversation
Paragraphs mixing a left tab stop with a right-aligned tab stop — the classic two-column signature block — were excluded from the anchored tab renderer by the `hasLeft && (hasCenter || hasRight)` guard and fell back to the plain tab path, which treats every tab as left-aligned. The right tab was rendered as a left tab, mis-wrapping the columns vs Word. Add a `left-right` anchored mode: when a paragraph has a left tab + a right tab (no center) and >= 2 tab characters, render a 3-zone grid (margin / left-tab / right-tab-right-aligned), reusing buildAnchoredTabZones and the same grid-anchoring approach as center-right. Fixes extend-hq#13. Co-Authored-By: Justin Copeland <justin.copeland@legalontech.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@jmcopeland is attempting to deploy a commit to the Extend Team on Vercel. A member of the Team first needs to authorize it. |
Refine the left-right anchored layout: collapse the trailing right tab (Word drops it once the column content runs past it) and render everything after the first tab as a single left-aligned, normally-wrapping right column, instead of a fixed right-aligned zone that overlapped the column text. Verified in the playground against the signature-block repro. Co-Authored-By: Justin Copeland <justin.copeland@legalontech.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A line break inside a tab-column paragraph is a shared row boundary: it must start a new line in every column and return to the first column. Tokenize the anchored zone builder on both tabs and newlines (newline => <br> into all zones + reset to column 0), and render the left-right zones as blocks so those breaks render. This makes the common two-line signature block (party name / 'On behalf of...') lay out as aligned two-column rows. Regression test covers the two-row case; full unit suite green. Co-Authored-By: Justin Copeland <justin.copeland@legalontech.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Scope note: this PR fixes the left + right tab-stop anchored two-column case (verified across a multi-variant signature-block repro; the Two adjacent plain tab-path mis-positioning bugs surfaced during validation but are out of scope here and tracked separately in #15: (1) a wrapped/second line's tab lands short of the stop when its preceding text is longer (variants using a left-tab-only paragraph or two tab-separated paragraphs), and (2) single-tab rows (the |
|
Superseding this in favor of #16. The left-right anchored grid here correctly handled the explicit-line-break signature block, but it mishandled the far more common no-line-break form (a run that wraps to the margin, e.g. the McKinsey signature block) by mashing the tab-delimited segments together. #16 instead makes the plain-tab path alignment-aware (right/center stops) on top of canvas-accurate measurement, which renders both the line-break and wrap forms correctly and also covers genuine right-aligned trailers. Closing; the work continues in #16. |
Summary
Fixes #13 — two-column signature blocks (a left tab stop + a right-aligned tab stop in the same paragraph) render with incorrect wrapping/positioning vs Word.
Root cause
paragraphAnchoredTabLayout(...)gates whether a paragraph uses the anchored tab renderer (buildAnchoredTabZones, which positions zones at the tab-stop coordinates). It bailed out for the exact signature-block pattern:So a
left tab + right tabparagraph fell back to the plain tab path, which resolves every tab as left-aligned (resolveNextTabStopPxjust advances the cursor to the next stop). Thew:val="right"tab was rendered as a left tab → wrong wrap.Fix
Add a
"left-right"anchored mode: when a paragraph has a left tab and a right tab (no center) with ≥ 2 tab characters, render a 3-zone CSS grid — zone 0 at the left margin, zone 1 left-aligned at the left tab, zone 2 right-aligned at the right tab — reusingbuildAnchoredTabZones(3)and the same grid-anchoring approach as the existingcenter-rightlayout. Threaded the new mode through both paragraph-render paths, the pretext line-count path, and the special-tab-layout gate.Test
tests/unit/left-right-tab-columns.test.ts— arenderToStaticMarkupregression asserting a left+right paragraph renders viadata-docx-tab-layout="left-right"with three zones (fails onmain, passes here).Full unit suite: 475 passed, 15 skipped, 0 failures — no regressions to the existing center / right / center-right / header-footer tab layouts.
Repro doc: https://github.com/jmcopeland/react-docx/raw/repro/tab-stop-column-wrap/repros/tab-stop-column-wrap.docx